using System;
using System.Linq;
using System.Linq.Expressions;
using Magiq.Tests.Support;
using NUnit.Framework;

namespace Magiq.Tests {
  public abstract class BaseMagiqProviderDeletesTest : BaseMagiqProviderTest {
    [Test]
    public void ShouldDeleteAll() {
      var count = TestClass1s.Count();
      TestClass1s.Delete().Should(Be.EqualTo(count));
      TestClass1s.Count().Should(Be.EqualTo(0));
    }

    [Test]
    public void ShouldDeleteWhereThatUsesStringProperty() {
      TestDelete(TestClass1s,
                 x => x.StringProperty == "sarasa");
    }

    [Test]
    public void ShouldDeleteWhereThatUsesAnotherStringProperty() {
      TestDelete(TestClass1s,
                 x => x.StringProperty == x.AnotherStringProperty);
    }

    [Test]
    public void ShouldDeleteComplexWhere() {
      TestDelete(TestClass1s,
                 x => (x.StringProperty == "sarasa" && x.IntProperty >= 3) ||
                      x.AnotherIntProperty < 12 &&
                      x.AnotherStringProperty != null);
    }

    [Test]
    public void ShouldDeleteWhereThatUsesSelfReference() {
      TestDelete(TestClass1s, x => x.SelfReference != null && x.SelfReference.IntProperty > 3);
    }

    [Test]
    public void ShouldDeleteWhereThatUsesStringPropertyNull() {
      TestDelete(TestClass1s,
                 x => x.StringProperty == null);
    }

    [Test]
    public void ShouldDeleteWhereThatUsesComposedStringProperty() {
      TestDelete(TestClass1s,
                 x => x.StringProperty == x.AnotherStringProperty + "la");
    }

    [Test]
    public void ShouldDeleteWhereThatUsesIntProperty() {
      var items = TestClass1s.Where(x => x.IntProperty == 3);
      var count = items.Count();
      items.Delete().Should(Be.EqualTo(count));
    }

    [Test]
    public void ShouldDeleteWhereThatUsesComposedIntProperty() {
      var items = TestClass1s.Where(x => x.IntProperty == x.AnotherIntProperty + 3);
      var count = items.Count();
      items.Delete().Should(Be.EqualTo(count));
    }

    [Test]
    public void ShouldDeleteWhereThatUsesAnotherIntProperty() {
      var items = TestClass1s.Where(x => x.IntProperty == x.AnotherIntProperty);
      var count = items.Count();
      items.Delete().Should(Be.EqualTo(count));
    }

    [Test]
    public void ShouldDeleteWhereThatUsesReference() {
      var r = TestClass2s.First();
      var items = TestClass1s.Where(x => x.Reference == r);
      var count = items.Count();
      items.Delete().Should(Be.EqualTo(count));
    }

    [Test]
    public void ShouldDeleteWhereThatUsesReferenceNull() {
      var items = TestClass1s.Where(x => x.Reference == null);
      var count = items.Count();
      items.Delete().Should(Be.EqualTo(count));
    }

    [Test]
    public void ShouldDeleteWhereThatUsesNullableIntProperty() {
      var items = TestClass1s.Where(x => x.NullableIntProperty == 3);
      var count = items.Count();
      items.Delete().Should(Be.EqualTo(count));
    }

    [Test]
    public void ShouldDeleteWhereThatUsesNullableIntPropertyNull() {
      var items = TestClass1s.Where(x => x.NullableIntProperty == null);
      var count = items.Count();
      items.Delete().Should(Be.EqualTo(count));
    }

    [Test]
    public void ShouldDeleteWhereThatUsesNullableIntPropertyWithIntProperty() {
      var items = TestClass1s.Where(x => x.NullableIntProperty == x.IntProperty);
      var count = items.Count();
      items.Delete().Should(Be.EqualTo(count));
    }


    [Test]
    public void ShouldDeleteWhereThatUsesNullableIntPropertyToNull() {
      var items = TestClass1s.Where(x => x.NullableIntProperty == null);
      var count = items.Count();
      items.Delete().Should(Be.EqualTo(count));
    }

    private static void TestDelete<T>(IQueryable<T> queryable, Expression<Func<T, bool>> where) where T : class {
      var items = queryable.Where(where);
      var count = items.Count();
      queryable.Where(where).Delete().Should(Be.EqualTo(count));
      queryable.Where(where.Compile()).Count().Should(Be.EqualTo(0));
    }
  }
}